#include "ModuleSURF.h"

////////////////////////////////////////////////////////////////////////////////
void ModuleSURF::init(QCVModuleHandlerInterface * parent)
{
  this->parent=parent;
  
  win=new QWidget();
  layout=new QVBoxLayout(win);
  QGridLayout * glayout1=new QGridLayout();
  QGridLayout * glayout2=new QGridLayout();
  QGridLayout * glayout3=new QGridLayout();
  
  use_mask=new QCheckBox(tr("Utilise un masque"));
  use_mask->setChecked(false);

	is_extended=new QCheckBox(tr("Etendu (128 - 64)"));
  is_extended->setChecked(true);
  
  mode=new QComboBox(win);
  mode->addItem("Detecteur (image -> keyspoints)");
  mode->addItem("Descripteur (image+keys -> descripteurs)");  
  //mode->addItem("Detecteur + Descripteur (image -> descripteurs)");
  
  sb_nOctaves=new QSpinBox(win);
  sb_nOctaves->setPrefix(tr("nOctaves="));
  sb_nOctaves->setValue(4);
	sb_nOctaves->setRange(1,9);
  sb_nOctaveLayers=new QSpinBox(win);
  sb_nOctaveLayers->setPrefix(tr("nOctaveLayers="));
  sb_nOctaveLayers->setValue(2);
	sb_nOctaveLayers->setRange(1,20);
  
  sb_threshold=new QDoubleSpinBox(win);
  sb_threshold->setPrefix(tr("hessian threshold="));
  sb_threshold->setValue(0);
  sb_threshold->setRange(-100,100);
  
  glayout1->addWidget(sb_threshold,0,1);
  
  glayout3->addWidget(use_mask,0,0);
	glayout3->addWidget(is_extended,0,1);

  glayout3->addWidget(sb_nOctaves,1,0);
  glayout3->addWidget(sb_nOctaveLayers,1,1);
  
  layout->addWidget(mode);
  layout->addLayout(glayout3);
  layout->addLayout(glayout1);
  layout->addLayout(glayout2);
  
  connect(sb_threshold,SIGNAL(valueChanged(double)),this,SLOT(changeSURFParams(double)));
  connect(sb_nOctaves,SIGNAL(valueChanged(int)),this,SLOT(changeSURFParams(int)));
  connect(sb_nOctaveLayers,SIGNAL(valueChanged(int)),this,SLOT(changeSURFParams(int)));  
  connect(mode,SIGNAL(currentIndexChanged(int)),this,SLOT(setSURFParams(int)));
	connect(is_extended,SIGNAL(stateChanged(int)),this,SLOT(setSURFParams(int)));

  mode->setCurrentIndex(0);
  surf=NULL;
	setSURFParams(mode->currentIndex());         
  surfTargets.clear();
}
////////////////////////////////////////////////////////////////////////////////
void ModuleSURF::free()
{
  delete win;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleSURF::getParams()
{
  return tr("%n;","",mode->currentIndex())+tr("%n;","",use_mask->isChecked())+tr("%n;","",is_extended->isChecked())
					+tr("%n;","",sb_nOctaves->value())+tr("%n;","",sb_nOctaveLayers->value())+tr("%n","",sb_threshold->value());
}
////////////////////////////////////////////////////////////////////////////////
bool ModuleSURF::setParams(QString params)
{
  QStringList list_params=params.split(";");
		
	if(list_params.size()==6)
	{
		mode->setCurrentIndex(list_params[0].toInt());
		use_mask->setChecked(list_params[1].toInt());
		is_extended->setChecked(list_params[2].toInt());
		sb_nOctaves->setValue(list_params[3].toInt());
		sb_nOctaveLayers->setValue(list_params[4].toInt());	
		sb_threshold->setValue(list_params[5].toInt());
		return true;
	}
	else
	{
		return false;
	}
}

QCVModuleInterface * ModuleSURF::clone()
{
	return new ModuleSURF;
}
//////////////////////////////////////////////////////////////////////////////// 
cv::Mat & ModuleSURF::process()
{
  if(!use_mask->isChecked()){mask.create(frame.rows,frame.cols,CV_8UC1);mask=255;}

	if(mode->currentIndex()==0)
  {
    surfTargets.clear();
    (*surf)(frame, mask, surfTargets);
    
    keypoints.create(surfTargets.size(),7);
    for(unsigned int i=0;i<surfTargets.size();i++)
    {
      keypoints(i,0)=surfTargets[i].pt.x;
      keypoints(i,1)=surfTargets[i].pt.y;
      keypoints(i,2)=surfTargets[i].size;
      keypoints(i,3)=surfTargets[i].angle;
      keypoints(i,4)=surfTargets[i].response;
			keypoints(i,5)=surfTargets[i].octave;//octave			
			keypoints(i,6)=surfTargets[i].class_id;//label
    }
    //on retourne la liste des points sous forme de matrice
    return keypoints;
  }
	if(mode->currentIndex()==1)
    (*surf)(frame, mask, surfTargets,descriptors,true);
  {
    
	
		
		descriptors_mat.create(descriptors.size()/surf->descriptorSize(),surf->descriptorSize());

		for(int j=0;j<descriptors.size()/surf->descriptorSize();j++){
		for (int i=0;i<surf->descriptorSize();i++){
			descriptors_mat(j,i)=descriptors[i+surf->descriptorSize()*j];
		}}
		
		//printf("desc.rows=%d desc.cols=%d desc_size=%d\n",descriptors_mat.rows,descriptors_mat.cols,descriptors.size());
		
    return descriptors_mat;
  }

}
////////////////////////////////////////////////////////////////////////////////
void ModuleSURF::setInput(int n,const cv::Mat & m)
{
  if(n==0)
	{
		frame.create(m.rows,m.cols,CV_8UC1);
    cvtColor(m, frame, CV_RGB2GRAY);
	}
	else if(n==1 && use_mask->isChecked())
	{
		mask=m.clone();
	}
	else if(n==1 || n==2)
  {
    //la il faut convertir la matrice en vecteur de points clefs
    surfTargets.clear();
		 cv::Mat_<float> keys=m; 
    for(int i=0;i<keys.rows;i++)
    {
      cv::KeyPoint pt(keys(i,0),
                      keys(i,1),
                      keys(i,2),
                      keys(i,3),
                      keys(i,4),
											keys(i,5),
											keys(i,6));
      surfTargets.push_back(pt);
    } 
  }
}
////////////////////////////////////////////////////////////////////////////////
QWidget* ModuleSURF::widget()
{
  return win;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleSURF::getName()
{
  return trUtf8("SURF");
}
////////////////////////////////////////////////////////////////////////////////
int ModuleSURF::nbInputs()
{
  return 1+use_mask->isChecked()+(mode->currentIndex()==1);
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleSURF::help(int id)
{
	if(id==-2)
	{
		 return tr("Module d'extration d'invarient d'echelle.");
	}	
	else if(id==-1)
	{
		if(mode->currentIndex()==0)
		{
			return tr("keyspoints");
		}
		else
		{
			return tr("descripteurs");
		}
	}
	else if(id==0)
	{
		return tr("image");
	}
  else if(id==1)
	{
		if(use_mask->isChecked())
		{
			return tr("image");
		}
		else
		{
			return tr("keyspoints");
		}
	}
	else if(id==2)
	{
		return tr("keyspoints");
	}
	else 
	{
		return tr("erreur");
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleSURF::setSURFParams(int type)
{                                           
  if(surf!=NULL)delete surf;
  
  surf=new cv::SURF(sb_threshold->value(),sb_nOctaves->value(),sb_nOctaveLayers->value(),is_extended->isChecked());
}            
void ModuleSURF::changeSURFParams(double n)
{
  setSURFParams(mode->currentIndex());
}
void ModuleSURF::changeSURFParams(int n)
{
  setSURFParams(mode->currentIndex());
}
////////////////////////////////////////////////////////////////////////////////
Q_EXPORT_PLUGIN2(ModuleSURF_plugin,ModuleSURF);                                                                               
